/*
 * Encriptador.cpp
 *
 *  Created on: 10/09/2010
 *      Author: julfc
 */

#include "Encriptador.h"

Encriptador::Encriptador() {
	this->tamanioMatriz = getTamanioMatriz();
	ManejadorConfiguracion mc;
	vector<string> parametros = mc.obtenerParamsLibspopc();
	string claveMatriz = parametros[1] + parametros[2];
	int h1 = Hash1(claveMatriz);
	int h2 = Hash2(claveMatriz);
	this->matriz = new Matriz(h1, h2, tamanioMatriz);
	this->tamanioMatriz = getTamanioMatriz();
	this->tamanioBloque = getTamanioBloque();
	Matriz* inversa = new Matriz(tamanioMatriz);
	inversa->matriz = this->matriz->calcularInversaLoca();
	this->matrizInversa = inversa;
}

int Encriptador::getTamanioMatriz() {
	ManejadorConfiguracion mc;
	long tam_bloques = mc.obtenerTamanioMatriz();
	return tam_bloques;
}

long Encriptador::getTamanioBloque() {
	ManejadorConfiguracion mc;
	long tam_bloques = mc.obtenerTamanioBloque() * mc.BYTES_IN_KB;
	return tam_bloques;
}

int Encriptador::Hash1(string clave){
	string encodeMd5 = md5(clave);
	int aux = (int)encodeMd5[5];
	if ((aux % 2) == 0)
		return aux + 1;
	else
		return aux;
}

int Encriptador::Hash2(string clave){
	string encodeMd5 = md5(clave);
	int aux = (int)encodeMd5[6];
		if ((aux % 2) == 0)
			return aux + 1;
		else
			return aux;
}

void Encriptador::nuevoEncriptar(char* bloque) {
	char* bloqueIterador = bloque;

	vector<unsigned char> bloquecito;
	vector<unsigned char> bloquecitoEncriptado;
	unsigned char auxChar;
	long tam_bloques = this->tamanioBloque;

	for (int kk = 0; kk < tam_bloques;) {
		memcpy(&(auxChar), bloqueIterador, sizeof(unsigned char));
		bloqueIterador+=sizeof(unsigned char);
		kk+=sizeof(unsigned char);
		bloquecito.push_back(auxChar);
	}
	bloquecitoEncriptado = this->matriz->nuevoObtenerVector(bloquecito);
	bloquecito.clear();
	memset(bloque, 0, tam_bloques);
	bloque[tam_bloques]='\0';
	bloqueIterador = bloque;
	for(unsigned int j = 0; j < bloquecitoEncriptado.size(); j++) {
		auxChar = bloquecitoEncriptado[j];
		memcpy(bloqueIterador, &auxChar, sizeof(unsigned char));
		bloqueIterador+= sizeof(unsigned char);
	}
	bloquecitoEncriptado.clear();
}

void Encriptador::encriptarPosta(char* bloque) {
	char* bloqueIterador = bloque;
	//char* aGuardar = bloque;
	char* aGuardar = (char*) malloc(tamanioBloque + 1);
	memset(aGuardar, 0, tamanioBloque);
	aGuardar[tamanioBloque]='\0';
	char* auxAguardar = aGuardar;
	char* bloqueAux;
	long tamBloques = this->tamanioBloque;
	long tamanioMatriz = this->tamanioMatriz;
    int valor;
    int valorEnt;
    int lalala;
    unsigned int vectJ;
    unsigned char auxChar;
    int matrizIJ;
    long kk=0;
    unsigned int zz = 0;
    while (kk < tamBloques) {
		for(int i =0; i < tamanioMatriz; i++){
			bloqueAux = bloque;
			bloqueAux+= zz*tamanioMatriz*sizeof(unsigned char);
			kk = zz*tamanioMatriz*sizeof(unsigned char);
			bloqueIterador = bloqueAux;
			valor = 0;
			for(int j=0; j < tamanioMatriz; j++){
				memcpy(&(auxChar), bloqueIterador, sizeof(unsigned char));
				bloqueIterador+= sizeof(unsigned char);
				kk+= sizeof(unsigned char);
				vectJ = (unsigned int)auxChar;
				matrizIJ = this->matriz->matriz[j][i];
				valor +=  vectJ* matrizIJ;

			}
			valorEnt = valor;
			lalala = valorEnt % 256;
			auxChar = (unsigned char)lalala;
			memcpy(auxAguardar, &auxChar, sizeof(unsigned char));
			auxAguardar+=sizeof(unsigned char);
		}
		zz++;
	}
    memcpy(bloque, aGuardar, tamBloques);
    free(aGuardar);
}

void Encriptador::desencriptarPosta(char* bloque) {
	char* bloqueIterador = bloque;
	char* aGuardar = (char*) malloc(tamanioBloque + 1);
	memset(aGuardar, 0, tamanioBloque);
	aGuardar[tamanioBloque]='\0';
	char* auxAguardar = aGuardar;
	char* bloqueAux;
	long tamBloques = this->tamanioBloque;
	long tamanioMatriz = this->tamanioMatriz;
	int valor;
	int valorEnt;
	int lalala;
	unsigned int vectJ;
	unsigned char auxChar;
	int matrizIJ;
	long kk=0;
	unsigned int zz = 0;

	while (kk < tamBloques) {
		for(int i =0; i < tamanioMatriz; i++){
			bloqueAux = bloque;
			bloqueAux+= zz*tamanioMatriz*sizeof(unsigned char);
			kk = zz*tamanioMatriz*sizeof(unsigned char);
			bloqueIterador = bloqueAux;
			valor = 0;
			for(int j=0; j < tamanioMatriz; j++){
				memcpy(&(auxChar), bloqueIterador, sizeof(unsigned char));
				bloqueIterador+= sizeof(unsigned char);
				kk+= sizeof(unsigned char);
				vectJ = (unsigned int)auxChar;
				//cout << vectJ;
				matrizIJ = this->matrizInversa->matriz[i][j];
				valor +=  vectJ* matrizIJ;

			}
			valorEnt = valor;
			lalala = valorEnt % 256;
			auxChar = (unsigned char)lalala;
			memcpy(auxAguardar, &auxChar, sizeof(unsigned char));
			auxAguardar+=sizeof(unsigned char);
		}
		zz++;
	}
	memcpy(bloque, aGuardar, tamBloques);
	free(aGuardar);
}

void Encriptador::nuevoDesencriptar(char* bloqueEncriptado) {
	char* bloqueIterador = bloqueEncriptado;

	vector<unsigned char> bloquecito;
	vector<unsigned char> bloquecitoDesEncriptado;
	unsigned char auxChar;
	long tam_bloques = this->tamanioBloque;

	for (int kk = 0; kk < tam_bloques;) {
		memcpy(&(auxChar), bloqueIterador, sizeof(unsigned char));
		bloqueIterador+=sizeof(unsigned char);
		kk+=sizeof(unsigned char);
		bloquecito.push_back(auxChar);
	}
	bloquecitoDesEncriptado = this->matrizInversa->nuevoObtenerVectorAlVerres(bloquecito);
	bloquecito.clear();
	memset(bloqueEncriptado, 0, tam_bloques);
	bloqueEncriptado[tam_bloques]='\0';
	bloqueIterador = bloqueEncriptado;
	for(unsigned int j = 0; j < bloquecitoDesEncriptado.size(); j++) {
		auxChar = bloquecitoDesEncriptado[j];
		memcpy(bloqueIterador, &auxChar, sizeof(unsigned char));
		bloqueIterador+= sizeof(unsigned char);
	}
	bloquecitoDesEncriptado.clear();
}

Encriptador::~Encriptador() {
	delete this->matriz;
	delete this->matrizInversa;
}
